package com.open.ssm.oss;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.security.SecureRandom;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;

@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class OSSClientUtils {
	
	private Logger logger = LoggerFactory.getLogger(OSSClientUtils.class);
	
	@Autowired
	private OSS ossClient;
	
	// 访问域名
	private String endpoint;
	
	// OSS存储空间bucket
	private String bucketName;
	
	/**
	 * 上传文件
	 *
	 * @param file 文件
	 * @param bucketName 存储空间Bucket lnint2017oss
	 * @param folder 上传文件目录  aiops/
	 */
	public String uploadFile(MultipartFile file, String bucketName, String folder) {
		logger.info("上传文件至OSS服务器开始-----------------------");
		String url = null;

		try {
			InputStream is = file.getInputStream();
			String path = file.getOriginalFilename();
			String fileName = path.substring(path.lastIndexOf(File.separator) + 1);
			String type = path.substring(path.lastIndexOf(".") + 1);
			SecureRandom randomS = new SecureRandom();
			int random = (int) (Math.abs(randomS.nextLong()) * 900L) + 10000;
			String fileNameNew = fileName.replace(fileName,
					String.valueOf(System.currentTimeMillis()) + String.valueOf(random) + "." + type);
			if (!file.isEmpty() && file.getSize() != 0L) {
				Long fileSize = file.getSize();
				ObjectMetadata metadata = new ObjectMetadata();
				metadata.setContentLength((long) is.available());
				metadata.setCacheControl("no-cache");
				metadata.setHeader("Pragma", "no-cache");
				metadata.setContentEncoding("utf-8");
				metadata.setContentType(getContentType(fileNameNew));
				metadata.setContentDisposition("filename/filesize=" + fileNameNew + "/" + fileSize + "Byte.");
				ossClient.putObject(bucketName, folder + fileNameNew, is, metadata);
				url = bucketName + "/" + folder + fileNameNew;
				//url = folder + fileNameNew;
			}
			if (is != null) {
				is.close();
			}

		} catch (OSSException e) {
			logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
		} catch (ClientException e) {
			logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
		} catch (IOException e) {
			logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
		} finally {

		}

		logger.info("上传文件至OSS服务器结束-----------------------，url="+url);
		return url;
	}
	
	/**
	 * 文件InputStream保存至OSS
	 *
	 * @param is InputStream
	 * @param bucketName 存储空间Bucket lnint2017oss
	 * @param folder 上传文件目录  aiops/
	 * @param fileName 文件名 b4f8665a-38bf-11ed-922c00046b9a7f43.jpg
	 */
	public String uploadFile(InputStream is, String bucketName, String folder, String fileName) {
		logger.info("上传base64文件至OSS服务器开始-----------------------");
		String url = null;
		try {
			ObjectMetadata metadata = new ObjectMetadata();
			metadata.setContentLength((long) is.available());
			metadata.setCacheControl("no-cache");
			metadata.setHeader("Pragma", "no-cache");
			metadata.setContentEncoding("utf-8");
			metadata.setContentType(getContentType(fileName));
			metadata.setContentDisposition("filename=" + fileName);
			ossClient.putObject(bucketName, folder + fileName, is, metadata);
			//https://lnint2017oss.oss-cn-shanghai.aliyuncs.com/aiops/mmbdf-mda/1672112362071-305751872.png
			url = "https://"+bucketName+"."+endpoint + "/" + folder + fileName;
		} catch (OSSException e) {
			logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
		} catch (ClientException e) {
			logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
		} catch (Exception e) {
			logger.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
		}

		logger.info("上传文件至OSS服务器结束-----------------------，url="+url);
		return url;
	}

	/**
	 * 下载文件
	 *
	 * @param bucketName 存储空间Bucket lnint2017oss
	 * @param objectName 文件名，包含路径，例如exampledir/exampleobject.txt
	 * @param
	 */
	public void downloadFile(String bucketName, String objectName, HttpServletRequest request, HttpServletResponse response) {
		logger.info("下载文件从OSS服务器开始-----------------------");
		try {
			String fileName = objectName.substring(objectName.lastIndexOf(File.separator) + 1);
			// 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元信息。
			OSSObject ossObject = ossClient.getObject(bucketName, objectName);
			// 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
			InputStream content = ossObject.getObjectContent();
            BufferedInputStream in = new BufferedInputStream(content);
            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
            response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName,"UTF-8"));
            byte[] data = new byte[1024];
            int L = 0;
            while((L=in.read(data))!=-1) {
                out.write(data, 0,L);
            }
            if(out!=null) {
                out.flush();
                out.close();
            }
            if(in != null) {
                in.close();
            }
		} catch (OSSException e) {
			logger.error("OSS服务器下载文件失败OSSException." + e.getMessage(), e);
		} catch (ClientException e) {
			logger.error("OSS服务器下载文件失败ClientException." + e.getMessage(), e);
		} catch (IOException e) {
			logger.error("OSS服务器下载文件失败IOException." + e.getMessage(), e);
		}

		logger.info("下载文件从OSS服务器结束-----------------------");
	}
	/**
	 * 下载文件
	 *
	 * @param bucketName 存储空间Bucket lnint2017oss
	 * @param objectName 文件名，包含路径，例如exampledir/exampleobject.txt
	 * @param
	 */
	public InputStream readFile(String bucketName, String objectName) {
		logger.info("下载文件从OSS服务器开始-----------------------");
		InputStream content = null;
		try {
			// 调用ossClient.getObject返回一个OSSObject实例，该实例包含文件内容及文件元信息。
			OSSObject ossObject = ossClient.getObject(bucketName, objectName);
			// 调用ossObject.getObjectContent获取文件输入流，可读取此输入流获取其内容。
			content = ossObject.getObjectContent();
		} catch (OSSException e) {
			logger.error("OSS服务器下载文件失败OSSException." + e.getMessage(), e);
		} catch (ClientException e) {
			logger.error("OSS服务器下载文件失败ClientException." + e.getMessage(), e);
		}

		logger.info("下载文件从OSS服务器结束-----------------------");
		return content;
	}
	/**
	 * 下载到本地文件
	 *
	 * @param bucketName 存储空间Bucket lnint2017oss
	 * @param objectName 文件名，包含路径，例如exampledir/exampleobject.txt
	 * @param pathName /home/mmbdf/download/exampleobject.txt
	 */
	public void downloadFile(String bucketName, String objectName, String pathName) {
		logger.info("下载到本地文件 开始-----------------------");
		try {
            // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
            // 如果未指定本地路径，则下载后的文件默认保存到程序所属项目对应本地路径中。
            ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));
        } catch (OSSException e) {
        	logger.error("OSS下载文件失败OSSException." + e.getMessage(), e);
        } catch (ClientException e) {
        	logger.error("OSS下载文件失败ClientException." + e.getMessage(), e);
        } catch (Exception e) {
        	logger.error("OSS下载文件失败Exception." + e.getMessage(), e);
        }

		logger.info("下载到本地文件 结束-----------------------");
	}

	// 生成下载链接
	public String getUrl(String bucketName, String key) {
		Date expiration = new Date(System.currentTimeMillis() + 315360000000L);
		URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
		return url != null ? url.toString() : null;
	}

	// 生成下载链接
	public String getUrl(String bucketName, String key, Date expiration) {
		URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
		return url != null ? url.toString() : null;
	}

	// 创建目录
	public String createFolder(String bucketName, String folder) {
		if (!ossClient.doesObjectExist(bucketName, folder)) {
			ossClient.putObject(bucketName, folder, new ByteArrayInputStream(new byte[0]));
			logger.info("创建文件夹成功");
			OSSObject object = ossClient.getObject(bucketName, folder);
			String fileDir = object.getKey();
			return fileDir;
		} else {
			return folder;
		}
	}

	// 删除文件
	public void deleteFile(String bucketName, String key) {
		ossClient.deleteObject(bucketName, key);
		logger.info("删除" + bucketName + "下的文件" + key + "成功");
	}

	// 关闭OSSClient
	public void shutdown() {
		if(ossClient != null) {
			ossClient.shutdown();
		}
	}

	public String getContentType(String fileName) {
		String fileExtension = fileName.substring(fileName.lastIndexOf("."));
		if (".bmp".equalsIgnoreCase(fileExtension)) {
			return "image/bmp";
		} else if (".gif".equalsIgnoreCase(fileExtension)) {
			return "image/gif";
		} else if (!".jpeg".equalsIgnoreCase(fileExtension) && !".jpg".equalsIgnoreCase(fileExtension)
				&& !".png".equalsIgnoreCase(fileExtension)) {
			if (".html".equalsIgnoreCase(fileExtension)) {
				return "text/html";
			} else if (".txt".equalsIgnoreCase(fileExtension)) {
				return "text/plain";
			} else if (".vsd".equalsIgnoreCase(fileExtension)) {
				return "application/vnd.visio";
			} else if (!".ppt".equalsIgnoreCase(fileExtension) && !"pptx".equalsIgnoreCase(fileExtension)) {
				if (!".doc".equalsIgnoreCase(fileExtension) && !"docx".equalsIgnoreCase(fileExtension)) {
					return ".xml".equalsIgnoreCase(fileExtension) ? "text/xml" : "image/jpeg";
				} else {
					return "application/msword";
				}
			} else {
				return "application/vnd.ms-powerpoint";
			}
		} else {
			return "image/jpeg";
		}
	}

	public String getEndpoint() {
		return endpoint;
	}

	public void setEndpoint(String endpoint) {
		this.endpoint = endpoint;
	}

	public String getBucketName() {
		return bucketName;
	}

	public void setBucketName(String bucketName) {
		this.bucketName = bucketName;
	}
}
